/**
 * Copyright (c) 2009-2011, chunquedong(YangJiandong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 
 * History:
 *     2010-05-05  Jed Young  Creation
 */
package chunmap.model.geom;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import chunmap.model.coord.Transform;
import chunmap.model.elem.Envelope;
import chunmap.model.elem.EnvelopeBuf;

/**
 * @author chunquedong
 * 
 */
public class MultiGeometry<E extends Geometry> extends AbstractGeometry
		implements GeometryCollection {

	protected List<E> geometrys;

	public MultiGeometry(List<? extends E> geometryList) {
		if (geometryList == null || geometryList.size() < 1) {
			throw new IllegalArgumentException();
		}

		geometrys = new ArrayList<E>();
		for (E g : geometryList) {
			geometrys.add(g);
		}
	}

	public E getGeometry(int index) {
		return geometrys.get(index);
	}

	public int size() {
		return geometrys.size();
	}

	@Override
	public Iterator<Geometry> iterator() {
		return new Iterator<Geometry>() {
			Iterator<E> it = geometrys.iterator();

			@Override
			public boolean hasNext() {
				return it.hasNext();
			}

			@Override
			public E next() {
				return it.next();
			}

			@Override
			public void remove() {
				throw new UnsupportedOperationException();
			}
		};
	}

	@Override
	protected Envelope calculateEnvelop() {
		EnvelopeBuf env = new EnvelopeBuf();
		for (E g : geometrys) {
			env.mergeEnvelop(g.getEnvelop());
		}
		return env.toEnvelop();
	}

	@Override
	public GeometryType getGeometryType() {
		return GeometryType.GeometryCollection;
	}

	/**
	 * GEOMETRYCOLLECTION(POINT(10 20),LINESTRING(10 30,40 50))
	 */
	@Override
	public String toString() {
		StringBuilder str = new StringBuilder();
		str.append("GEOMETRYCOLLECTION(");
		for (Geometry g : geometrys) {
			str.append(g.toString() + ",");
		}
		str.deleteCharAt(str.lastIndexOf(","));
		str.append(")");
		return str.toString();
	}

	@Override
	public Geometry getBoundary() {
		List<Geometry> bs = new ArrayList<Geometry>();
		for (Geometry g : geometrys) {
			Geometry gb = g.getBoundary();
			if (gb == null)
				continue;
			GeometryCollection gc = (GeometryCollection) gb;
			for (Geometry geo : gc) {
				bs.add(geo);
			}
		}
		return new MultiGeometry<Geometry>(bs);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see chunmap.model.geom.Geometry#checkValid()
	 */
	@Override
	protected boolean isSimple() {
		for (Geometry g : geometrys) {
			if (g.isValid() == false) {
				return false;
			}
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	// 泛型强制转换警告
	@Override
	public Geometry transform(Transform transf) {
		List<E> geometryList = new ArrayList<E>();
		for (E g : geometrys) {
			geometryList.add((E) g.transform(transf));
		}
		return new MultiGeometry<E>(geometryList);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((geometrys == null) ? 0 : geometrys.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (getClass() != obj.getClass())
			return false;
		@SuppressWarnings("rawtypes")
		MultiGeometry other = (MultiGeometry) obj;
		
		if (geometrys == null) {
			if (other.geometrys != null)
				return false;
		}
		
		for (E g : geometrys) {
			if(!g.equals(other)){
				return false;
			}
		}
		
		return true;
	}
}